from abc import ABC, abstractmethod
from langchain_core.prompts import ChatPromptTemplate  # 改为使用ChatPromptTemplate
from langchain_community.llms import Tongyi
import os
from typing import Dict
from langchain.tools.retriever import create_retriever_tool
from mytools import vector_store_tools
from langchain_core.runnables import RunnableParallel, RunnablePassthrough

current_dir = os.path.dirname(os.path.abspath(__file__))

# 回退到项目根目录（mypro/），然后定位文件
path = os.path.join(current_dir, "../../mypro/my_file/my_text.txt")
path = os.path.normpath(path)
retriever=vector_store_tools.VectorStoreTools(path).get_retriever('ai_session')


retriever_tool=create_retriever_tool(
    retriever=retriever,
    name="insurance_clause_retriever",
    description="检索相关条款内容，回答用户问题参考"

)


class Factory(ABC):
    # 定义一个抽象方法，用于提示用户输入
    @abstractmethod
    def _prompt(self):
        pass
    # 定义一个抽象方法，用于生成用户输入的响应
    @abstractmethod
    def generate_response(self, user_input: str):
        pass

    def _get_retriever(self):
        """默认使用全局retriever，子类可重写"""
        return retriever

class MedicalInsurance(Factory):
    # 定义一个方法，用于生成聊天提示模板
    def _prompt(self):
        # 从消息列表中生成聊天提示模板
        return ChatPromptTemplate.from_messages([
            ("system", """你是资深医疗保险专家，专注于健康险、重疾险、医疗补充险等产品。请遵循以下原则：
                1. 回答专业准确，引用最新医保政策
                2. 对医学术语做通俗解释
                3. 区分不同保险产品的覆盖范围
                4. 提供实用建议时注明"建议："前缀
                5. 对复杂问题分点回答
                ...
                
                """),
            ("human", "{user_input}")
        ])

    # 定义一个方法，用于生成响应
    def generate_response(self, user_input: str):
        # 创建一个Tongyi对象，用于调用模型
        llm = Tongyi(
            model='qwen-plus',
            api_key=os.getenv('DASHSCOPE_API_KEY'),
        )
        # 创建一个链式调用，用于生成响应
        chain = (
                RunnableParallel({
                    "context": self._get_retriever() | (lambda docs: "\n".join([d.page_content for d in docs])),
                    "user_input": RunnablePassthrough()
                })
                | self._prompt()
                | llm
        )

        # 调用链式调用，生成响应
        return chain.invoke(user_input)


# 其他保险类也做相同修改...
class AccidentInsurance(Factory):
    def _prompt(self):
        return ChatPromptTemplate.from_messages([
            ("system", "你是专业的意外保险顾问"),
            ("human", "{user_input}")
        ])

    def generate_response(self, user_input: str):
        llm = Tongyi(
            model='qwen-plus',
            api_key=os.getenv('DASHSCOPE_API_KEY'),
        )
        chain = (
                RunnableParallel({
                    "context": self._get_retriever() | (lambda docs: "\n".join([d.page_content for d in docs])),
                    "user_input": RunnablePassthrough()
                })
                | self._prompt()
                | llm
        )

        return chain.invoke(user_input)


class PropertyInsurance(Factory):
    def _prompt(self):
        return ChatPromptTemplate.from_messages([
            ("system", """你是专业财产保险顾问，请遵循以下原则：
                    1. 基于提供的保险条款内容回答问题
                    2. 明确说明保障范围和免赔额
                    3. 引用条款时要具体到条款编号
                    4. 提供风险防范建议
                    
                    回答格式：
                    - 条款依据：【引用具体条款】
                    - 核心内容：分点说明
                    - 专业建议：提供实用建议
                    
                    
                    """),
            ("human", """相关保险条款内容：
    {context}

    问题：{user_input}""")
        ])

    def generate_response(self, user_input: str):
        llm = Tongyi(
            model='qwen-plus',
            api_key=os.getenv('DASHSCOPE_API_KEY'),
        )
        chain = (
                RunnableParallel({
                    "context": self._get_retriever() | (lambda docs: "\n".join([d.page_content for d in docs])),
                    "user_input": RunnablePassthrough()
                })
                | self._prompt()
                | llm
        )

        return chain.invoke(user_input)



class InsuranceFactory:
    @staticmethod
    def create_insurance(insurance_type: str) -> Factory:
        insurance_classes: Dict[str, type] = {
            "medical": MedicalInsurance, #医疗保险
            "accident": AccidentInsurance, #事故保险
            "property": PropertyInsurance #财产办校
        }
        if insurance_type not in insurance_classes:
            raise ValueError(f"Unknown insurance type: {insurance_type}")
        return insurance_classes[insurance_type]()


if __name__ == "__main__":
    try:
        # 测试医疗保险
        medical = InsuranceFactory.create_insurance("medical")
        response = medical.generate_response(
            "请问重大疾病保险的等待期一般是多久？什么情况下不赔付？"
        )

        print("医疗保险回答：")
        print(response)
        # 测试意外保险
        accident = InsuranceFactory.create_insurance("accident")
        print("\n意外保险回答：")
        print(accident.generate_response("交通事故导致的伤害如何赔付？需要哪些材料？"))
        # 测试财产保险
    except ValueError as e:
        print(f"错误: {e}")